# Copyright (c) 2006-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Gou Pengfei

import os
import optparse
import sys
from os.path import join as joinpath

import m5
from m5.defines import buildEnv
from m5.objects import *
from m5.util import addToPath, fatal


if buildEnv['FULL_SYSTEM']:
    fatal("This script requires syscall emulation mode (*_SE).")

addToPath('../common')

import Simulation
from Caches import *
from cpu2000 import *

# This is the name of this configuration. This should be the same as name of this file
conf = ((os.path.basename(sys.argv[0])).split('.'))[0]

config_path = os.path.dirname(os.path.abspath(__file__))
config_root = os.path.dirname(config_path)
m5_root = os.path.dirname(config_root)

work_dir = joinpath(os.environ['HOME'], 'workdir')

parser = optparse.OptionParser()

execfile(os.path.join(config_root, "common", "Options.py"))

(options, args) = parser.parse_args()

# Define CPU, system and Memory Hierarchy
cpu = AtomicEdgeCPU(cpu_id = 0,
                    maxPass = 1024,
                    simPointSim = True,
                    preExecuteMode = False
                    )

cpu.clock = '2GHz'

system = System(cpu = cpu,
                physmem = PhysicalMemory(latency = '1ps',range = AddrRange(Addr('0MB'), size = '256MB')),
                membus = Bus(clock='1THz'),
                mem_mode = 'atomic')

system.cpu.physmem_port = system.physmem.port

system.physmem.port = system.membus.port
cpu.connectMemPorts(system.membus)

root = Root(system = system)

# Since we're in batch mode, dont allow tcp socket connections
m5.disableAllListeners()

# set default maxtick... script can override
# -1 means run forever
maxtick = m5.MaxTick

benchname = []

if options.bench:

    benchname = options.bench

    if not options.input_set:
        print >> sys.stderr, "Don't know what input set to use"
        sys.exit(1)
        
    try:
        exec("workload = %s('trips', 'linux', '%s', '%s', 'hyperblock')" % (options.bench, options.input_set, conf))
        process = workload.makeLiveProcess()

        # Set simpoint
        cpu.simPointStartFunctionName = workload.edgeSimpointStartFunctionName
        cpu.simPointEndFunctionName = workload.edgeSimpointEndFunctionName
        cpu.simPointCallNum = workload.edgeSimpointStartFunctionCallNum
        cpu.simPointRetNum = workload.edgeSimpointEndFunctionRetNum
        cpu.simPointMode = "StartPoint"

        print 
        print "Making checkpoint at name:%s; num of calls:%d" % \
                (cpu.simPointStartFunctionName,cpu.simPointCallNum)
        print "The end of this simpoint is at name:%s; num of rets:%d" % \
                (cpu.simPointEndFunctionName,cpu.simPointRetNum)
        print
    except:
        print >>sys.stderr, "Unable to find workload for %s" % options.bench
        sys.exit(1)
       
# tweak configuration for specific test
root.system.cpu.workload = process

# instantiate configuration
m5.instantiate(root)

# simulate until program terminates
exit_event = m5.simulate()

cpt_dir = joinpath(work_dir, 'checkpoint')
cpt_name = 'cpt.spt.3.2.%s' % benchname

if exit_event.getCause() == "simulate() limit reached":
    m5.checkpoint(root, joinpath(cpt_dir, cpt_name))

print 'Exiting @ tick', m5.curTick(), 'because', exit_event.getCause()
